using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Dimok.Data.Database;
using Dimok.Exceptions;
using Dimok.Data.DataSources;

namespace Dimok.Web.UI {

	#region Events & Handlers

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>	Additional information for form view ex inserted events. </summary>
	///
	/// <remarks>	Dimon, 12/21/2010. </remarks>
	////////////////////////////////////////////////////////////////////////////////////////////////////

	public class FormViewExInsertedEventArgs :FormViewInsertedEventArgs {
		public DataTable InsertedTable;
		public DataKey InsertedDataKey;
		public FormViewExInsertedEventArgs(DataKey dataKey,DataTable table,int affectedRows,Exception e)
			: base(affectedRows,e) {
			InsertedTable = table;
			InsertedDataKey = dataKey;
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>	Additional information for form view ex updated events. </summary>
	///
	/// <remarks>	Dimon, 12/21/2010. </remarks>
	////////////////////////////////////////////////////////////////////////////////////////////////////

	public class FormViewExUpdatedEventArgs :FormViewUpdatedEventArgs {
		public DataTable UpdatedTable;
		public DataKey UpdatedDataKey;
		public FormViewExUpdatedEventArgs(DataKey dataKey,DataTable table,int affectedRows,Exception e)
			: base(affectedRows,e) {
			UpdatedTable = table;
			UpdatedDataKey = dataKey;
		}
	}
	public delegate void FormViewExInsertedEventHandler(object sender,FormViewExInsertedEventArgs e);
	public delegate void FormViewExUpdatedEventHandler(object sender,FormViewExUpdatedEventArgs e); 
	#endregion

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>	Form view ex. </summary>
	///
	/// <remarks>	Dimon, 12/21/2010. </remarks>
	////////////////////////////////////////////////////////////////////////////////////////////////////

	public class FormViewEx :FormView {

		#region Events
		public event FormViewExInsertedEventHandler ItemInsertedEx;
		public event EventHandler ItemCanceled;
		public event FormViewExUpdatedEventHandler ItemUpdatedEx;
		public event EventHandler DataSourceSelected;
		#endregion

		#region Proprties

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// Gets or sets a value indicating whether the <see cref="M:
		/// System.Web.UI.WebControls.BaseDataBoundControl.DataBind" /> method should be called. 
		/// </summary>
		///
		/// <value>	true if requires data binding, false if not. </value>
		///
		/// ### <returns>	
		/// The returned value is true if the data-bound control's <see cref="M:
		/// System.Web.UI.WebControls.BaseDataBoundControl.DataBind" /> method should be called before the
		/// control is rendered; otherwise, the value is false. 
		/// </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public new bool RequiresDataBinding { get { return base.RequiresDataBinding; } set { base.RequiresDataBinding = value; } }
		AObjectDataSourceBase _ds = null;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the ds. </summary>
		///
		/// <value>	The ds. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		AObjectDataSourceBase DS {
			get {
				if(_ds != null) return _ds;
				return _ds = NamingContainer.FindControl(DataSourceID) as AObjectDataSourceBase;
			}
		}

		List<Control> _dss = null;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the ss. </summary>
		///
		/// <value>	The d ss. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		List<Control> DSs {
			get {
				if(_dss != null) return _dss;
				return _dss = Find.ChildrenByType(NamingContainer,typeof(AObjectDataSourceBase));
			}
		}
		#endregion

		#region Event Handlers

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Event handler. Called by DS for selected events. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="SmartException">	Thrown when smart. </exception>
		/// <exception cref="InnerException">	Thrown when inner. </exception>
		///
		/// <param name="sender">	Source of the event. </param>
		/// <param name="e">			Object data source status event information. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		void DS_Selected(object sender,ObjectDataSourceStatusEventArgs e) {
			if(e.Exception != null) {
				TargetInvocationException tie = e.Exception as TargetInvocationException;
				if(tie == null) return;
				e.ExceptionHandled = true;
				SmartException se = new SmartException(tie.InnerException);
				if(Config.UI.DebugMode) throw se;
				else throw tie.InnerException;
			}
			if (DataSourceSelected != null) DataSourceSelected(this, new EventArgs());
		}
		#endregion

		#region Overrides

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Raises the load event. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="SmartException">	Thrown when smart. </exception>
		///
		/// <param name="e">	Object data source status event information. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected override void OnLoad(EventArgs e) {
			try {
				base.OnLoad(e);
			} catch (Exception exc) { throw new SmartException(exc); }
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Raises the <see cref="E:System.Web.UI.Control.Init" /> event. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="SmartException">	Thrown when smart. </exception>
		///
		/// <param name="e">	An <see cref="T:System.EventArgs" /> that contains the event data. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected override void OnInit(EventArgs e) {
			try {
				base.OnInit(e);
				foreach (AObjectDataSourceBase ds in DSs)
					ds.Selected += new ObjectDataSourceStatusEventHandler(DS_Selected);
			} catch (Exception exc) {
				throw new SmartException(exc);
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Raises the <see cref="E:System.Web.UI.WebControls.FormView.ItemUpdating" /> event. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="SmartException">	Thrown when smart. </exception>
		///
		/// <param name="e">	A <see cref="T:System.Web.UI.WebControls.FormViewUpdateEventArgs" /> that
		/// 									contains the event data. </param>
		///
		/// ### <exception cref="T:System.Web.HttpException">	This method is called when the <see cref="T:
		/// 																									System.Web.UI.WebControls.FormView" />
		/// 																									control is not bound to a data source control,
		/// 																									the user did not cancel the update operation,
		/// 																									and an event handler is not registered for
		/// 																									the event. </exception>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected override void OnItemUpdating(FormViewUpdateEventArgs e) {
			//if(e.CommandArgument == "Cancel") return;
			try {
				try { if (!Page.IsValid) return; } catch { }
				base.OnItemUpdating(e);
				Control parent = Find.ParentControl(this.Parent) as Control;
				AObjectDataSourceBase odsb = Find.ControlByID(parent, DataSourceID) as AObjectDataSourceBase;
				if (odsb == null) return;
				bool isInsert = e.Keys.Count > 0 && e.Keys[0] == DBNull.Value;

				if (!isInsert)
					foreach (object key in e.OldValues.Keys) {
						if ((e.NewValues[key] + "") == (e.OldValues[key] + ""))
							e.NewValues.Remove(key);
					}
				else
					foreach (object key in e.NewValues.Keys)
						if ((e.NewValues[key]+"")  == "")
							e.NewValues.Remove(key);
						
				DataTable dt = odsb.UpdateFields(e.NewValues, e.Keys);
				if (e.Keys.Count > 0 && isInsert) {
					if (ItemInsertedEx != null)
						ItemInsertedEx(this, new FormViewExInsertedEventArgs(new DataKey(e.Keys), dt, dt.Rows.Count, null));
				} else if (ItemUpdatedEx != null)
					ItemUpdatedEx(this, new FormViewExUpdatedEventArgs(new DataKey(e.Keys), dt, dt.Rows.Count, null));
			}catch(System.Threading.ThreadAbortException){
			} catch (Exception exc) { throw new SmartException(exc); }
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Raises the <see cref="E:System.Web.UI.WebControls.FormView.ItemUpdated" /> event. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="SmartException">	Thrown when smart. </exception>
		/// <exception cref="InnerException">	Thrown when inner. </exception>
		///
		/// <param name="e">	A <see cref="T:System.Web.UI.WebControls.FormViewUpdatedEventArgs" /> that
		/// 									contains the event data. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected override void OnItemUpdated(FormViewUpdatedEventArgs e) {
			try {
				base.OnItemUpdated(e);
				if (e.Exception == null || e.Exception is NotSupportedException) {
					e.ExceptionHandled = true;
					return;
				}
				TargetInvocationException tie = e.Exception as TargetInvocationException;
				if (tie == null) return;
				e.ExceptionHandled = true;
				if (Config.UI.DebugMode) throw new SmartException(tie.InnerException);
				else throw tie.InnerException;
			} catch (Exception exc) { throw new SmartException(exc); }
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Raises the <see cref="E:System.Web.UI.WebControls.FormView.ItemCommand" /> event. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="e">	A <see cref="T:System.Web.UI.WebControls.FormViewCommandEventArgs" /> that
		/// 									contains the event data. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected override void OnItemCommand(FormViewCommandEventArgs e) {
			base.OnItemCommand(e);
			if(e.CommandName == "Update" && (e.CommandArgument + "") == "Cancel" && ItemCanceled != null) 
				ItemCanceled(this, new EventArgs());
		}
		#endregion

	}
}
